package com.fxhy.utils;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.imageio.ImageIO;

import com.fxhy.bean.AgentUser;
import com.fxhy.contants.MyConstant;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;

/**
 * 二维码生成图片，保存到项目根目录
 * @author lifengyao
 *
 */
@Slf4j
public class QrCodeUtil {
	
	/**
     * 谷歌 - 生成包含字符串信息的二维码图片
     * @param outputStream 文件输出流路径
     * @param content 二维码携带信息
     * @param qrCodeSize 二维码图片大小
     * @param imageFormat 二维码的格式
     * @throws WriterException 
     * @throws IOException 
     */
    public static boolean createQrCodeByZX(OutputStream outputStream, String content, int qrCodeSize, String imageFormat) throws WriterException, IOException{  
            //设置二维码纠错级别ＭＡＰ
            Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();  
            hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);  // 矫错级别  
            QRCodeWriter qrCodeWriter = new QRCodeWriter();  
            //创建比特矩阵(位矩阵)的QR码编码的字符串  
            BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);  
            // 使BufferedImage勾画QRCode  (matrixWidth 是行二维码像素点)
            int matrixWidth = byteMatrix.getWidth();  
            BufferedImage image = new BufferedImage(matrixWidth-200, matrixWidth-200, BufferedImage.TYPE_INT_RGB);  
            image.createGraphics();  
            Graphics2D graphics = (Graphics2D) image.getGraphics();  
            graphics.setColor(Color.WHITE);  
            graphics.fillRect(0, 0, matrixWidth, matrixWidth);  
            // 使用比特矩阵画并保存图像
            graphics.setColor(Color.BLACK);  
            for (int i = 0; i < matrixWidth; i++){
                for (int j = 0; j < matrixWidth; j++){
                    if (byteMatrix.get(i, j)){
                        graphics.fillRect(i-100, j-100, 1, 1);  
                    }
                }
            }
            return ImageIO.write(image, imageFormat, outputStream);  
    }  
    
    
      
    /**
     * 谷歌 - 读二维码并输出携带的信息
     */
    public static void readQrCodeByZX(InputStream inputStream) throws IOException{  
        //从输入流中获取字符串信息
        BufferedImage image = ImageIO.read(inputStream);  
        //将图像转换为二进制位图源
        LuminanceSource source = new BufferedImageLuminanceSource(image);  
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));  
        QRCodeReader reader = new QRCodeReader();  
        Result result = null ;  
        try {
         result = reader.decode(bitmap);  
        } catch (ReaderException e) {
            e.printStackTrace();  
        }
        System.out.println(result.getText());
    }
    
//    /**
//     * QR工具生成二维码
//     * @param content 内容
//     * @param qrPath 生成文件地址
//     * @return 返回是否正确
//     * @throws Exception
//     */
//    public static boolean creatTxmByQR(String content,String qrPath) throws Exception {
//        Qrcode qrcode = new Qrcode();
//        qrcode.setQrcodeErrorCorrect('M');
//        qrcode.setQrcodeEncodeMode('B');
//        qrcode.setQrcodeVersion(100);
//
//        byte[] bstr = content.getBytes("UTF-8");//返回用指定名字命名的字节数组值
//        BufferedImage bi = new BufferedImage(700, 700, BufferedImage.TYPE_INT_RGB);//实例化指定参数的BufferedImage
//        Graphics2D g = bi.createGraphics();//返回一个呈现指定 BufferedImage 的 Graphics2D 对象
//        g.setBackground(Color.WHITE); // 设置该Graphics2D 对象的背景颜色
//        g.clearRect(0, 0, 700, 700); //擦除指定的矩形，并且用一个透明的颜色填充它
//        g.setColor(Color.BLACK); // 条码颜色
//        if (bstr.length > 0 && bstr.length < 123) {
//            boolean[][] b = qrcode.calQrcode(bstr); //通过calQrcode函数将byte数组转换成boolean数组 ,然后依据编码后的boolean数组绘图 
//            for (int i = 0; i < b.length; i++) {
//                for (int j = 0; j < b.length; j++) {
//                    if (b[j][i]) {
//                        g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3); //填充指定的矩形
//                    }
//                }
//            }
//        }
//        g.dispose(); //处理图形上下文，并释放系统资源
//        bi.flush();//将生成的BufferedImage序列化到磁盘
//        
//        return ImageIO.write(bi, "jpg", new File(qrPath));//将生成的二维码以图片的形式写入相应的文件
//    }
//    
//    /**
//     * 生成带logo的二维码
//     * @param content
//     * @param logoPath
//     * @return
//     */
//    public static boolean createLogoQrcode(String content, String logoPath, String qrPath) {
//    	BufferedImage bufferedImage = null;
//    	
//        try {
//            Qrcode logoQrCode = new Qrcode();
//            logoQrCode.setQrcodeErrorCorrect('M');
//            logoQrCode.setQrcodeEncodeMode('B');
//            logoQrCode.setQrcodeVersion(10);
//
//            bufferedImage = new BufferedImage(700, 700, BufferedImage.TYPE_INT_RGB);
//            Graphics2D gs = bufferedImage.createGraphics();
//            gs.setBackground(Color.WHITE);
//            gs.setColor(Color.BLUE);
//            gs.clearRect(0, 0, 700, 700);
//
//            byte[] contents = content.getBytes("utf-8");
//
//            int opx = 2;
//            if (contents.length > 0 && contents.length < 130) {
//                boolean[][] codeOut = logoQrCode.calQrcode(contents);
//                for (int i = 0; i < codeOut.length; i++) {
//                    for (int j = 0; j < codeOut.length; j++) {
//                        if (codeOut[j][i]) {
//                            gs.fillRect(j * 3 + opx, i * 3 + opx, 3, 3);
//                        }
//                    }
//                }
//            } else {
//                log.error("QRCode content bytes length = " + contents.length + " not in [ 0,130 ]. ");
//            }
//
//            // logo图片高度
//            Image logo = ImageIO.read(new URL(logoPath));
//            int widthLogo = logo.getWidth(null) > bufferedImage.getWidth() * 2 / 10 ? (bufferedImage.getWidth() * 2 / 10) : logo.getWidth(null);
//            int heightLogo = logo.getHeight(null) > bufferedImage.getHeight() * 2 / 10 ? (bufferedImage.getHeight() * 2 / 10) : logo.getWidth(null);
//
//            // 设置logo图片的位置
//            int x = (bufferedImage.getWidth() - widthLogo) / 2;
//            int y = (bufferedImage.getHeight() - heightLogo) / 2;
//
//            gs.drawImage(logo,x,y,widthLogo,heightLogo,null);
//
//            gs.dispose();
//            bufferedImage.flush();
//            
//            // 生成二维码QRCode图片
//            File imgFile = new File(qrPath);
//            // 生成的图片在D盘下，名为 qrCode.png
//            return ImageIO.write(bufferedImage, "jpg", imgFile);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//		return false;
//        
//    }
    
    /**
     * 谷歌 - 可控大小的二维码生成  不带logo
     * @param qrPath 输出地址
     * @param imgSize 大小
     * @param content 内容
     * @return 返回是否成功
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean createZXCode (String qrPath,int imgSize,String content){
    	int width = imgSize;//二维码图片的宽度
		int height = imgSize;//二维码图片的高度
		
		//定义二维码内容参数
		HashMap hints = new HashMap();
		//设置字符集编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		//设置容错等级，在这里我们使用M级别
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		//设置边框距
		hints.put(EncodeHintType.MARGIN, 2);
		
		//生成二维码
		try {
			//指定二维码内容
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
	
			//指定生成图片的保存路径
			Path file = new File(qrPath).toPath();
			//生成二维码
			MatrixToImageWriter.writeToPath(bitMatrix, "jpg", file);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
    }
    
    private static final int QRCOLOR = 0xFF000000; // 默认是黑色
    private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色
    
    // 用于设置QR二维码参数
    private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
        private static final long serialVersionUID = 1L;
        {
            put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置QR二维码的纠错级别（H为最高级别）具体级别信息
            put(EncodeHintType.CHARACTER_SET, "utf-8");// 设置编码方式
            put(EncodeHintType.MARGIN, 0);
        }
    };
    
    /**
     * 谷歌 - 生成带logo的二维码
     * @param logoFileBuffer logo流
     * @param codeFile 二维码输出文件
     * @param content 内容
     * @param note 标记
     * @param size 图片大小
     * @return 返回是否成功
     */
    public static  boolean drawLogoQRCode(BufferedImage logoFileBuffer, File codeFile, String content, String note,int size) {
        BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            // 参数顺序分别为：编码内容，编码类型，生成图片宽度，生成图片高度，设置参数
            BitMatrix bm = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 开始利用二维码数据创建Bitmap图片，分别设为黑（0xFFFFFFFF）白（0xFF000000）两色
            for (int x = 0; x < size; x++) {
                for (int y = 0; y < size; y++) {
                    image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
                }
            }

            int width = image.getWidth();
            int height = image.getHeight();
            // 构建绘图对象
            Graphics2D g = image.createGraphics();
            // 读取Logo图片
            BufferedImage logo = logoFileBuffer;
            // 开始绘制logo图片
            g.drawImage(logo, width * 2 / 5, height * 2 / 5, width * 2 / 10, height * 2 / 10, null);
            g.dispose();
            if(logo != null){
            	logo.flush();
            }

            image.flush();

            return ImageIO.write(image, "png", codeFile); // TODO
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
	
	/**
	 * 生成下载二维码
	 * @param qrCode 二维码内容
	 * @param user 用户
	 * @return
	 */
	public static String getQrImgURLForSetDown(String qrCode,AgentUser user){
		String qrPath = "C:/pic/qrXZ/XZ"+user.getUserId()+".jpg";
		boolean createFlag;
		try {
			//createFlag = createQrCodeByZX(new FileOutputStream(new File(qrPath)),qrCode,700,"jpg");
//			createFlag = creatTxmByQR(qrCode, qrPath);
//			createFlag = createZXCode(qrPath, 700, ApkLink.DEFAULT_LINK,"https://game-1256953255.cos.ap-guangzhou.myqcloud.com/share/share_friend.jpg");
			
			BufferedImage logoFileBuffer = getBufferedImageForURL("https://game-1256953255.cos.ap-guangzhou.myqcloud.com/share/share_friend.jpg");
			File qrFile = new File(qrPath);
			createFlag = drawLogoQRCode(logoFileBuffer, qrFile, "下载地址", qrPath, 400);
			
			if(createFlag){
	        	log.info("下载地址二维码生成成功! 文件地址在:{}  " + qrPath);
	        }else{
	        	qrPath = null;
	        }
		}  catch (Exception e) {
			log.error("下载地址二维码生成报错!" + e.getMessage());
			e.printStackTrace();
			return null;
		}
        
		return qrPath;
	}
	
	private static BufferedImage getBufferedImageForURL(String filePath) throws IOException {
        /**
         * asBufferedImage() 返回BufferedImage
         */
        BufferedImage thumbnail = Thumbnails.of(new URL(filePath))
        		.scale(1)
        		.asBufferedImage();
        return thumbnail;
        
    }



	/**
	 * 获取绑定页面地址二维码地址
	 * @param user 邀请人
	 * @return 返回二维码地址
	 */
	public static Map<String,String>  getQrImgURLForSetPhone(AgentUser user){
		Map<String,String> map = new HashMap<String,String>();
		String qrPath = "C:/pic/qrBD/BD"+user.getUserId()+".jpg";
		boolean createFlag;
		Integer sharedByUserId = user.getUserId();  //被邀请人的id
		String content = MyConstant.DEFAULT_BDVIEW+sharedByUserId;
		
		if(new File(qrPath).exists()){
			map.put("qrPath", qrPath);
			map.put("qrCode", content);
			log.info("绑定跳转页面地址二维码存在: " + qrPath);
		}else{
			try {
				createFlag = createZXCode(qrPath, 400, content);
				
				if(createFlag){
					map.put("qrPath", qrPath);
					map.put("qrCode", content);
		        	log.info("绑定跳转页面地址二维码生成成功! 文件地址在:{}  " + qrPath);
		        }else{
		        	qrPath = null;
		        }
			} catch (Exception e) {
				log.error("绑定地址二维码生成报错!" + e.getMessage());
				e.printStackTrace();
				return null;
			}
		}
		return map;
	}
	
	/**
	 * 获取联运邀请页面地址二维码地址
	 * @param user 邀请人
	 * @return 返回二维码地址
	 */
	public static Map<String,String>  getQrImgURLForAgentInvite(AgentUser user,String key){
		Map<String,String> map = new HashMap<String,String>();
		String qrPath = "C:/pic/qrInvite/"+user.getUserId()+".jpg";  

		String content = MyConstant.DEFAULT_INVITE_VIEW + key;
		
		if(new File(qrPath).exists()){
			map.put("qrPath", qrPath);
			map.put("qrCode", content);
			log.info("联运邀请跳转页面地址二维码存在: " + qrPath);
		}else{
			try {
				if(createZXCode(qrPath, 300, content)){
					map.put("qrPath", qrPath);
					map.put("qrCode", content);
		        	log.info("联运邀请跳转页面地址二维码生成成功! 文件地址在:{}  " + qrPath);
		        }else{
		        	qrPath = null;
		        }
			} catch (Exception e) {
				log.error("联运邀请地址二维码生成报错!" + e.getMessage());
				e.printStackTrace();
				return null;
			}
		}
		return map;
	}
	
//	public static void main(String[] args) throws FileNotFoundException, IOException {
//		File file = new File("C:/1.jpg");
//		FileInputStream ips = new FileInputStream(file);
//		readQrCodeByZX(ips);
//	}
}
